package rjeutsky.ui;

import java.io.PrintStream;
import java.util.LinkedList;
import java.util.List;

import rjeutsky.models.ApplicationModel;
import rjeutsky.models.CardThema;
import rjeutsky.models.OldCard;
import rjeutsky.models.TypeEnum;
import rjeutsky.ui.models.MenuAction;
import rjeutsky.ui.models.MenuItem;

public class ConsoleUi {
	protected ApplicationModel model;
	protected ConsoleMenu mainMenu;
	protected ConsoleMenu serializersMenu;
	protected PrintStream console = System.out;
	
	public ConsoleUi(ApplicationModel model){
		this.model = model;
		initMainMenu();
		initSerializersMenu();
	}
	
	public void Run(){
		mainMenu.printMenu();
		mainMenu.processMenu();
	}
	
	protected void printCardsList(){
		console.println("----- Cards list -----");
		for(OldCard card : model.getCards()){
			console.println(card);
		}
	}
	
	protected void initData(){
		model.initRandomData(10);
		printCardsList();
	}
	
	protected void clearCards(){
		model.clearCards();
	}
	
	protected void selectSAXSerializer(){
		model.setSAX();
	}
	
	protected void selectSTAXSerializer(){
		model.setSTAX();
	}
	
	protected void selectDomSerializer(){
		model.setDOM();
	}
	
	protected void addNewElement(){
		EnumConsoleRequest<CardThema> themaRequest = new EnumConsoleRequest<CardThema>(CardThema.ARCHITECTURE);
		themaRequest.setRequestText("Enter card thema");
		themaRequest.Run();
		BooleanConsoleRequest isSentRequest = new BooleanConsoleRequest();
		isSentRequest.setRequestText("Enter whether the card was sent");
		isSentRequest.Run();
		EnumConsoleRequest<TypeEnum> typeRequest = new EnumConsoleRequest<TypeEnum>(TypeEnum.ADVERTISEMENT);
		typeRequest.setRequestText("Enter card type");
		typeRequest.Run();
		StringConsoleRequest countryRequest = new StringConsoleRequest();
		countryRequest.setAllowsEmpty(false);
		countryRequest.setRequestText("Enter country");
		countryRequest.Run();
		IntegerConsoleRequest yearRequest = new IntegerConsoleRequest();
		yearRequest.setRequestText("Enter year");
		yearRequest.Run();
		StringConsoleRequest authorRequest = new StringConsoleRequest();
		authorRequest.setAllowsEmpty(true);
		authorRequest.setRequestText("Enter author (empty if not known)");
		authorRequest.Run();
		StringConsoleRequest valuableRequest = new StringConsoleRequest();
		valuableRequest.setAllowsEmpty(true);
		valuableRequest.setRequestText("Enter valuability(if any)");
		valuableRequest.Run();
		
		String author = authorRequest.getValue();
		if (author.equals("")){
			author = null;
		}
		String valuable = valuableRequest.getValue();
		if (valuable.equals("")){
			valuable = null;
		}
		
		model.addNewCard((CardThema) themaRequest.getValue(), isSentRequest.getValue(), (TypeEnum) typeRequest.getValue(),
				countryRequest.getValue(), yearRequest.getValue(), author, valuable);
		
		console.println("new card added");
		mainMenu.printMenu();
	}
	
	protected void save(){
		if (checkSerializer()) {
			String fileName = requestFileName();
			if (model.Save(fileName)) {
				console.println("file saved");
			} else {
				console.println("file could not be saved");
			}
		}
	}
	
	protected void load(){
		if (checkSerializer()) {
			String fileName = requestFileName();
			if (model.Load(fileName)) {
				console.println("file loaded");
				printCardsList();	
			} else {
				console.println("file could not be loaded");
			}
		}
	}
	
	protected void changeSerializer(){
		serializersMenu.printMenu();
		serializersMenu.processMenu();
		mainMenu.printMenu();
	}
	
	protected void showSerializerInfo(){
		if (checkSerializer()){
			console.println(model.getSerializer().getInfo());
		}
	}
	
	protected void initMainMenu(){
		List<MenuItem> mainMenuItems = new LinkedList<MenuItem>();
		mainMenuItems.add(new MenuItem("h", "help", new MenuAction() {
			@Override
			public boolean doAction() {
				mainMenu.printMenu();
				return true;
			}
		}));
		mainMenuItems.add(new MenuItem("p", "print old card list", new MenuAction() {
			@Override
			public boolean doAction() {
				printCardsList();
				return true;
			}
		}));
		mainMenuItems.add(new MenuItem("i", "fill old card list with initial data", new MenuAction() {
			@Override
			public boolean doAction() {
				initData();
				return true;
			}
		}));
		mainMenuItems.add(new MenuItem("c", "clear old card list", new MenuAction() {
			@Override
			public boolean doAction() {
				clearCards();
				return true;
			}
		}));
		mainMenuItems.add(new MenuItem("a", "add new old card", new MenuAction() {
			@Override
			public boolean doAction() {
				addNewElement();
				return true;
			}
		}));
		mainMenuItems.add(new MenuItem("s", "save to xml", new MenuAction() {
			@Override
			public boolean doAction() {
				save();
				return true;
			}
		}));
		mainMenuItems.add(new MenuItem("l", "load from xml", new MenuAction() {
			@Override
			public boolean doAction() {
				load();
				return true;
			}
		}));
		mainMenuItems.add(new MenuItem("r", "change serializer", new MenuAction() {
			@Override
			public boolean doAction() {
				changeSerializer();
				return true;
			}
		}));
		mainMenuItems.add(new MenuItem("f", "print serializer info", new MenuAction() {
			@Override
			public boolean doAction() {
				showSerializerInfo();
				return true;
			}
		}));
		mainMenuItems.add(new MenuItem("q", "quit", new MenuAction() {
			@Override
			public boolean doAction() {
				//just return false to quit
				return false;
			}
		}));
		mainMenu = new ConsoleMenu(mainMenuItems);
	}
	
	protected void initSerializersMenu(){
		List<MenuItem> serializersMenuItems = new LinkedList<MenuItem>();
		serializersMenuItems.add(new MenuItem("sax", "select SAX parser", new MenuAction() {
			@Override
			public boolean doAction() {
				selectSAXSerializer();
				return false;
			}
		}));
		serializersMenuItems.add(new MenuItem("stax", "select STAX parser", new MenuAction() {
			@Override
			public boolean doAction() {
				selectSTAXSerializer();
				return false;
			}
		}));
		serializersMenuItems.add(new MenuItem("dom", "select DOM parser", new MenuAction() {
			@Override
			public boolean doAction() {
				selectDomSerializer();
				return false;
			}
		}));
		serializersMenu = new ConsoleMenu(serializersMenuItems);
	}
	
	protected boolean checkSerializer(){
		if (model.getSerializer() == null) {
			console.println("no serializer selected");
			return false;
		}
		return true;
	}
	
	protected String requestFileName(){
		StringConsoleRequest fileNameRequest = new StringConsoleRequest();
		fileNameRequest.setAllowsEmpty(false);
		fileNameRequest.setRequestText("Enter file name");
		fileNameRequest.Run();
		return fileNameRequest.getValue();
	}
}
